package cn.hxth.cloud.provider.service.impl;

import cn.hxth.cloud.api.common.constant.ProcedureStatus;
import cn.hxth.cloud.api.common.util.AbstractBaseServiceImpl;
import cn.hxth.cloud.api.common.util.DateProvider;
import cn.hxth.cloud.api.domain.*;
import cn.hxth.cloud.api.mapper.ProductionOrderMapper;
import cn.hxth.cloud.api.mapper.SteelsMapper;
import cn.hxth.cloud.api.rabbitmq.RabbitMQSender;
import cn.hxth.cloud.provider.handler.ProductionHandler;
import cn.hxth.cloud.provider.handler.ProductionHandlerFactory;
import cn.hxth.cloud.provider.handler.ProductionHandlerResult;
import cn.hxth.cloud.provider.service.ProductionService;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ProductionServiceImpl extends AbstractBaseServiceImpl implements ProductionService {
    @Autowired
    private ProductionOrderMapper productionOrderMapper ;
    private  final Logger logger = LoggerFactory.getLogger(ProductionServiceImpl.class) ;
    @Autowired
    private SteelsMapper steelsMapper ;
    @Autowired
    private DateProvider dateProvider ;
    @Autowired
    private ProductionHandlerFactory productionHandlerFactory;
   @Autowired
    public ProductionServiceImpl(RabbitMQSender rabbitMQSender, RedisTemplate<String, String> redisTemplate, DateProvider dateProvider) {
        super(rabbitMQSender, redisTemplate, dateProvider);
    }

    @Override
    public Boolean insertProductionOrder(List<ProductionOrder> productionOrders,String mid) throws Exception {
       try {
           Map<Long,SteelsInputOrderItem> steelsInputOrderItemMap = null ;
           this.productionOrderMapper.insertList(productionOrders)  ;
           for (ProductionOrder productionOrder:productionOrders){
               Steels steels = this.steelsMapper.selectByPrimaryKey(productionOrder.getSid());
               SteelsOutputOrder order = new SteelsOutputOrder() ;
               order.setCount(productionOrder.getSteelsCount());
               order.setSid(productionOrder.getSid());
               order.setMid(mid);
               order.setPid(productionOrder.getId());
               order.setProductionOrder(productionOrder);
               productionOrder.setSteels(steels);
               if(steels.getInventory()-steels.getLockedInventory() >=productionOrder.getSteelsCount()) {
                   order.setMakeDate(dateProvider.getCurrentTime());
                   productionOrder.setProcedureStatus(ProcedureStatus.READING);
                  super.sendMessage("wms",order,"insertSteelsOutputOrder",mid);
               }
               else {
                   redisTemplate.opsForValue().set("steelsOutputOrder_"+productionOrder.getId(),JSONObject.toJSONString(order));
                   String jsonStr = redisTemplate.opsForValue().get("steelsInputOrderItem") ;
                   if(jsonStr == null){
                        steelsInputOrderItemMap = new HashMap<>() ;
                   }
                   else {
                       steelsInputOrderItemMap = JSONObject.parseObject(jsonStr,new TypeReference<Map<Long,SteelsInputOrderItem>>(){}) ;
                   }

                   SteelsInputOrderItem steelsInputOrderItem = new SteelsInputOrderItem() ;
                   steelsInputOrderItem.setCount(productionOrder.getSteelsCount()+1000);
                   steelsInputOrderItem.setSid(productionOrder.getSid());
                   if(!steelsInputOrderItemMap.containsKey(steelsInputOrderItem.getSid())){
                       steelsInputOrderItemMap.put(steelsInputOrderItem.getSid(),steelsInputOrderItem) ;
                   }
                   else{
                       SteelsInputOrderItem item = steelsInputOrderItemMap.get(steelsInputOrderItem.getSid());
                       item.setCount(steelsInputOrderItem.getCount()+item.getCount());
                   }




               }


           }
           if(steelsInputOrderItemMap != null){
               redisTemplate.opsForValue().set("steelsInputOrderItem", JSONObject.toJSONString(steelsInputOrderItemMap));
           super.sendMessage("inventory",productionOrders,"updateSteelsInventoryForOrder",mid);
           }


       }catch (Exception e){
           logger.error("error",e);
           return  false ;
       }
       return  true ;
    }

    @Override
    public Boolean updateStatus(ProductionOrder productionOrder) {
        Example example = new Example(ProductionOrder.class) ;
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("id",productionOrder.getId()) ;
        example.excludeProperties("procedureStatus") ;
        this.productionOrderMapper.updateByPrimaryKeySelective(productionOrder) ;

        return true ;
    }

    @Override
    public Boolean startProducing(Long id) {
        ProductionOrder productionOrder = this.productionOrderMapper.selectByPrimaryKey(id);
        ProductionHandler productionHandler = productionHandlerFactory.getProductionHandler(productionOrder);
        try {
            return  productionHandler.execute(productionOrder) ;
        } catch (Exception e) {
            logger.error("error",e);
            return  false ;
        }
    }

    @Override
    public Boolean doNext(Long id) {
        ProductionOrder productionOrder = this.productionOrderMapper.selectByPrimaryKey(id);
        ProductionHandler productionHandler = productionHandlerFactory.getProductionHandler(productionOrder);
        productionHandler.setResult(new ProductionHandlerResult(true,true));
        try {
            return  productionHandler.execute(productionOrder) ;
        } catch (Exception e) {
            logger.error("error",e);
            return  false ;
        }
    }

    @Override
    public void insertTurnoff(Long id, List<Turnoff> turnoffs) {
        ProductionOrder productionOrder = productionOrderMapper.selectByPrimaryKey(id) ;
        productionOrder.setTurnoffs(turnoffs);
        try {
            super.sendMessage("check",productionOrder,"insertCheckOrder",null);
        } catch (Exception e) {
            logger.error("error",e);

        }
    }
}
